home *** CD-ROM | disk | FTP | other *** search
/ Tech Win 1999 February / TECH Win 02-1999 Disc A.iso / ols / lzh / passwin.lzh / source / passwin.c next >
Encoding:
C/C++ Source or Header  |  1998-05-19  |  11.4 KB  |  401 lines

  1. #include <windows.h>
  2. #include "resource.h"
  3.  
  4. LRESULT CALLBACK WndProc( HWND, UINT, WPARAM, LPARAM );
  5.  
  6. // アプリケーションの名前を登録
  7. char szAppName[] = "passwin";
  8.  
  9. // 標準の argc, argv を利用可能にするための宣言
  10. #define argc __argc
  11. #define argv __argv
  12. extern int argc;
  13. extern char **argv;
  14.  
  15. HWND hwnd;
  16. HWND hDesktopWindow;
  17. HWND hProgmanWindow;
  18. HANDLE hInstance;
  19. RECT rectClientReserved;
  20. BOOL fShown = FALSE;
  21. UINT ArraySize = 128;
  22.  
  23. typedef struct WINStag
  24. {
  25.     HWND hwnd;
  26.     RECT rc;
  27. } WINS;
  28. WINS* hWindowsArray;
  29.  
  30. NOTIFYICONDATA nid;
  31.  
  32. UINT NumberOfWindows;
  33.  
  34. int RestoreInt( char* section, char* key, int def );
  35. void ReserveInt( char* section, char* key, int i );
  36. void ModifyWindowRgn( void );
  37. HWND SetUnderWindowThrough( int n );
  38. BOOL CALLBACK EnumWindowsProc( HWND hEnumWnd, LPARAM lParam );
  39. void FreeWindowsArray( void );
  40. void ChangeWindowRgn( WINS );
  41. void ResetAllWindows( void );
  42.  
  43.  
  44. // プログラムのエントリポイント
  45. int PASCAL WinMain( HANDLE hInstance, HANDLE hPrevInstance,
  46.                                 LPSTR lpszCmdParam, int nCmdShow )
  47. {
  48.     MSG         msg;
  49.     WNDCLASS    wndclass;
  50.  
  51.     int xPos = RestoreInt( "Settings", "xPos", 0 );
  52.     int yPos = RestoreInt( "Settings", "yPos", 0 ); 
  53.     int cWidth = RestoreInt( "Settings", "Width", 280 );
  54.     int cHeight = RestoreInt( "Settings", "Height", 100 );
  55.  
  56.  
  57.     // 重複起動を防ぐ
  58.     if( FindWindow( "PASSWIN", szAppName ) != NULL ) return FALSE;
  59.  
  60.     hDesktopWindow = GetDesktopWindow();
  61.     hProgmanWindow = FindWindow( "Progman", NULL );
  62.     // wndclass の定義
  63.     wndclass.style          = 0;
  64.     wndclass.lpfnWndProc    = WndProc;
  65.     wndclass.cbClsExtra     = 0;
  66.     wndclass.cbWndExtra     = 0;
  67.     wndclass.hInstance      = hInstance;
  68.     wndclass.hIcon          = LoadIcon( hInstance, IDI_APPLICATION );
  69.     wndclass.hCursor        = LoadCursor( NULL, IDC_ARROW );
  70.     wndclass.hbrBackground  = GetStockObject( WHITE_BRUSH );
  71.     wndclass.lpszMenuName   = NULL;
  72.     wndclass.lpszClassName  = szAppName;
  73.     // wndclass を登録する
  74.     RegisterClass( &wndclass );
  75.     
  76.     // ウィンドウを作成する
  77.     hwnd = CreateWindowEx( WS_EX_WINDOWEDGE | WS_EX_CLIENTEDGE,
  78.                         szAppName,             // window class name
  79.                         "PASS THROUGH WINDOW", // window caption
  80.                         WS_OVERLAPPEDWINDOW,    // window style
  81.                         xPos,                   // initial x position
  82.                         yPos,                   // initial y position
  83.                         cWidth,                 // initial x size
  84.                         cHeight,                // initial y size
  85.                         NULL,                   // parent window handle
  86.                         NULL,                   // window menu handle
  87.                         hInstance,              // program instance handle
  88.                         NULL );                 // creation parameters
  89.  
  90.     nid.cbSize = sizeof(NOTIFYICONDATA);
  91.     nid.hWnd = hwnd;
  92.     nid.uID = 1112;
  93.     nid.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP;
  94.     nid.uCallbackMessage = 1112;
  95.     nid.hIcon = LoadIcon( hInstance, MAKEINTRESOURCE(IDI_ICON) );
  96.     strcpy( nid.szTip, "Pass through Window" );
  97.  
  98.     Shell_NotifyIcon( NIM_ADD, &nid );
  99.  
  100.     ModifyWindowRgn();
  101.     hWindowsArray = (WINS*)malloc( ArraySize*sizeof(WINS) );
  102.  
  103.     ShowWindow( hwnd, SW_HIDE );
  104.     ResetAllWindows();
  105.     fShown = FALSE;
  106.     UpdateWindow( hwnd );
  107.  
  108.  
  109.     while( GetMessage( &msg, NULL, 0, 0 ) )
  110.     {
  111.         TranslateMessage( &msg );
  112.         DispatchMessage( &msg );
  113.     }
  114.     Shell_NotifyIcon( NIM_DELETE, &nid );
  115.     return msg.wParam;
  116. }
  117.  
  118. LRESULT CALLBACK WndProc( HWND hwnd, UINT message, UINT wParam, LONG lParam )
  119. {
  120.     static POINT pt;
  121.     static UINT  nTimer;
  122.     static HDC   hDC;
  123.     static char szCursorPos[128];
  124.     static RECT rc;
  125.     static PAINTSTRUCT ps;
  126.     static int xPos, yPos;
  127.     static int cWidth, cHeight;
  128.  
  129.     switch( message )
  130.     {
  131.         case WM_CREATE:
  132.             hInstance = ( (LPCREATESTRUCT) lParam )->hInstance;
  133.             nTimer = SetTimer( hwnd, 0, 100, NULL );
  134.             return 0;
  135.  
  136.         case WM_SIZE:
  137.             ResetAllWindows();
  138.             ModifyWindowRgn();
  139.             SetUnderWindowThrough( 0 );
  140.             return 0;
  141.  
  142.         case WM_MOVE:
  143.             ResetAllWindows();
  144.             SetUnderWindowThrough( 0 );
  145.             break;
  146.  
  147.         case 1112:
  148.             switch( lParam )
  149.             {
  150.                 case 0x201: // LBUTTONDOWN
  151. //                    if( fShown == TRUE ) break;                    
  152.                     ShowWindow( hwnd, SW_SHOWNORMAL );
  153. //                    ResetAllWindows();
  154.                     ModifyWindowRgn();
  155.                     SetUnderWindowThrough( 0 );
  156.                     fShown = TRUE;
  157.                     break;
  158.                 case 0x204: // RBUTTONDOWN
  159. //                    if( fShown == FALSE ) break;
  160.                     ShowWindow( hwnd, SW_HIDE );
  161.                     ResetAllWindows();
  162.                     fShown = FALSE;
  163.                     break;
  164.             }
  165.             break;
  166.  
  167.         case WM_ACTIVATE:
  168.             ResetAllWindows();
  169.             switch( LOWORD(wParam) )
  170.             {
  171.                 case WA_ACTIVE:
  172.                 case WA_CLICKACTIVE:
  173.                     if( fShown == FALSE ) break;
  174.                     ModifyWindowRgn();
  175.                     SetUnderWindowThrough( 0 );
  176.                     break;
  177.                 default:
  178.                     /* I took a misstake such that it is good 
  179.                     to let restore pass-throughing the windows normal
  180.                     when this is going to nonactive.
  181.                     But in future, I may notice a good way, so I preserve
  182.                     a little code. */
  183.                     if( fShown == FALSE ) break;
  184.                     ModifyWindowRgn();
  185.                     SetUnderWindowThrough( 0 );
  186.                     if( IsIconic( hwnd ) )
  187.                     {
  188.                         ResetAllWindows();
  189.                     }
  190.                     break;
  191.             }
  192.             break;
  193.  
  194.         case WM_DESTROY:
  195.             ResetAllWindows();
  196.             FreeWindowsArray();
  197.             GetWindowRect( hwnd, &rc );
  198.             ReserveInt( "Settings", "xPos", rc.left );
  199.             ReserveInt( "Settings", "yPos", rc.top );
  200.             ReserveInt( "Settings", "Width", rc.right - rc.left );
  201.             ReserveInt( "Settings", "Height", rc.bottom - rc.top );
  202.             PostQuitMessage( 0 );
  203.             return 0;
  204.     }
  205.     return DefWindowProc( hwnd, message, wParam, lParam );
  206. }
  207.  
  208. int RestoreInt( char* section, char* key, int def )
  209. {
  210.     /* レジストリから整数値を復元
  211.        section: セクション
  212.        key:     キー
  213.        def: デフォルト整数値
  214.        e.g. i = RestoreInt( "FOO", "BAR", 10 );
  215.        FOOセクションのBARキーの内容をiに代入。もし値がなければ10 */
  216.     HKEY hKey;
  217.     char szKey[256];
  218.     int i;
  219.     int size = sizeof(int);
  220.     LONG err;
  221.     wsprintf( szKey, "Software\\OTOBE\\PASSWIN\\%s", section );
  222.     if( RegOpenKeyEx( HKEY_CURRENT_USER, szKey, 
  223.                     0, KEY_READ, &hKey ) != ERROR_SUCCESS )
  224.     {
  225.         return def;
  226.     }
  227.     err = RegQueryValueEx( hKey, key, 0, NULL, (LPBYTE)&i, (LPDWORD)&size );
  228.     if( err != ERROR_SUCCESS )
  229.     {
  230.         return def;
  231.     }
  232.     RegCloseKey( hKey );
  233.     return (int)i;
  234. }
  235.  
  236. void ReserveInt( char* section, char* key, int i )
  237. {
  238.     /* レジストリに整数値を保管
  239.        section: セクション
  240.        key:     キー
  241.        sz:      保管整数値
  242.        e.g. ReserveInt( "FOO", "BAR", 10 );
  243.             FOO セクションの下の BAR エントリに10という値を保管。*/
  244.     HKEY hKey;
  245.     DWORD dwDisposition;
  246.     char szKey[256];
  247.     wsprintf( szKey, "Software\\OTOBE\\PASSWIN\\%s", section );
  248.     if( RegCreateKeyEx( HKEY_CURRENT_USER, szKey, 
  249.                     0, "", REG_OPTION_NON_VOLATILE, KEY_WRITE, 
  250.                     NULL, &hKey, &dwDisposition ) != ERROR_SUCCESS )
  251.     {
  252.         MessageBox( NULL, "Error in RegCreateKey", NULL, MB_OK );
  253.         return;
  254.     }
  255.     RegSetValueEx( hKey, key, 0, REG_DWORD, (BYTE *)&i, sizeof(int) );
  256.     RegCloseKey( hKey );
  257. }
  258.  
  259. void ModifyWindowRgn( void )
  260. {
  261.     RECT        rectWindow, rectClient;
  262.     HRGN        hrgnWindow, hrgnClient;
  263.     POINT        pt;
  264.     int            cx, cy;
  265.  
  266.     /* Now, we want to create a region that contains the window's 
  267.        components without client area.
  268.        Because we want to create such a region, we want to use
  269.        CreateRectRgn(Indirect) Function.
  270.        After we create two regions, the window region and the
  271.        client region, we will create the region that are the
  272.        difference of them.
  273.        We have already got the two rectangles. But one is by
  274.        screen coordinate, another is by client coordinate.
  275.        First, we translate client coordinate to screen one.
  276.        Because the left and top coordinates of client area
  277.        by client coordinate are always 0. We set pt struct
  278.        the left-top corner of client area by screen coordinate.
  279.        Note that the calues in rectClient structure is by
  280.        client coordinate. We want to use this values.
  281.        So, if we use OffsetRect Function to shift the values to
  282.        set client area the left-top corner of screen as the whole
  283.        window are put to the proper the corner.
  284.        Second, we create both regions.
  285.        Finally, We create the region as the difference of
  286.        two regions, which we set the new region to first one. */
  287.  
  288.     GetWindowRect( hwnd, &rectWindow );
  289.     GetClientRect( hwnd, &rectClient );
  290.  
  291.     pt.x = pt.y = 0;
  292.     ClientToScreen( hwnd, &pt );
  293.     cx = pt.x - rectWindow.left;
  294.     cy = pt.y - rectWindow.top;
  295.     OffsetRect( &rectClient, cx, cy );
  296.  
  297.     rectWindow.right -= rectWindow.left;
  298.     rectWindow.bottom -= rectWindow.top;
  299.     rectWindow.left = rectWindow.top = 0;
  300.  
  301.     hrgnClient = CreateRectRgnIndirect( &rectClient );
  302.     hrgnWindow = CreateRectRgnIndirect( &rectWindow );
  303.     CombineRgn( hrgnWindow, hrgnWindow, hrgnClient, RGN_DIFF );
  304.     SetWindowRgn( hwnd, hrgnWindow, TRUE );
  305.     DeleteObject( hrgnClient );
  306.     return;
  307. }
  308.  
  309. HWND SetUnderWindowThrough( int n )
  310. {
  311. /* This function returns the window handle that lies under this
  312.    application, PASSWIN. */
  313.     UINT i;
  314.     NumberOfWindows = 0;
  315.     EnumWindows( EnumWindowsProc, 1 );
  316.  
  317.     for( i = 0; i < NumberOfWindows; i++ )
  318.     {
  319.         ChangeWindowRgn( hWindowsArray[i] );
  320.     }
  321.     return NULL;
  322. }
  323.  
  324. BOOL CALLBACK EnumWindowsProc( HWND hEnumWnd, LPARAM lParam )
  325. {
  326.     /* We create hWindowsArray.
  327.        This contains an array of window handles.
  328.        The windows of which handles are contained in
  329.        hWindowsArray intersects our window.
  330.        the indexes are from 0 to NumberOfWindows-1.
  331.     */
  332.     
  333.     RECT rcEnum, rcThis, rc;
  334.  
  335.     if( !IsWindowVisible( hEnumWnd ) )
  336.     {
  337.         return TRUE;
  338.     }
  339.     if( hEnumWnd == hwnd || hEnumWnd == hDesktopWindow || hEnumWnd == hProgmanWindow )
  340.     {
  341.         return TRUE;
  342.     }
  343.  
  344.     GetWindowRect( hEnumWnd, &rcEnum );
  345.     GetWindowRect( hwnd, &rcThis );
  346.  
  347.     if( IntersectRect( &rc, &rcThis, &rcEnum ) == 0 )
  348.     {
  349.         return TRUE;
  350.     }
  351.     
  352.     if( NumberOfWindows >= ArraySize - 1 )
  353.     {
  354.         ArraySize += 16;
  355.         hWindowsArray = (WINS*)realloc( hWindowsArray, ArraySize*sizeof(WINS) );
  356.     }
  357.     hWindowsArray[NumberOfWindows].hwnd = hEnumWnd;
  358.     hWindowsArray[NumberOfWindows].rc = rc;
  359.     NumberOfWindows++;
  360.     return TRUE;
  361. }
  362.  
  363. void FreeWindowsArray( void )
  364. {
  365.     free( hWindowsArray );
  366. }
  367.  
  368. void ChangeWindowRgn( WINS wins )
  369. {
  370.     RECT        rectTarget;
  371.     HRGN        hrgnTarget, hrgnThrough;
  372.     /* First we get window's rectangle of target window.
  373.        we have to move it to left-top corner of screen.
  374.        Second, we have to move the target area.
  375.        The amount of to move is the same of that of target window. */
  376.     GetWindowRect( wins.hwnd, &rectTarget );
  377.     rectTarget.right -= rectTarget.left;
  378.     rectTarget.bottom -= rectTarget.top;
  379.     wins.rc.left -= rectTarget.left;
  380.     wins.rc.right -= rectTarget.left;
  381.     wins.rc.top -= rectTarget.top;
  382.     wins.rc.bottom -= rectTarget.top;
  383.     rectTarget.left = rectTarget.top = 0;
  384.  
  385.     hrgnThrough = CreateRectRgnIndirect( &wins.rc );
  386.     hrgnTarget  = CreateRectRgnIndirect( &rectTarget );
  387.     CombineRgn( hrgnTarget, hrgnTarget, hrgnThrough, RGN_DIFF );
  388.     SetWindowRgn( wins.hwnd, hrgnTarget, TRUE );
  389.     DeleteObject( hrgnThrough );
  390.     return;
  391. }
  392.  
  393. void ResetAllWindows( void )
  394. {
  395.     UINT i;
  396.     for( i = 0; i < NumberOfWindows; i++ )
  397.     {
  398.         SetWindowRgn( hWindowsArray[i].hwnd, NULL, TRUE );
  399.     }
  400. }
  401.